import React, {PropsWithChildren, useMemo} from 'react';
import { observer } from "mobx-react-lite";

import ProCesium, { type CEType, type CEComponentType, type CesiumType, Viewer, CesiumUtil } from "vendor/components/pro-cesium";
import { getEnv } from "@/constants";

import { MapCtx } from "./ctx";
import { GisMapStore } from "./model";
import MapTool from "./MapTool";


export { MapCtx }
export type { GisMapStore } from "./model";
export type {
    CEType,
    CEComponentType,
    CesiumType
}


export interface Earth3dVisProps{
    // 基础图层
    baseLayers?:{
        label?: string,
        groupLayer: {
            // 高德地图
            amap?:{
                url?: string;
                protocol?: "http" | "https",
                style?: "img" | "elec" | "cva", // img: 卫星图, elec: 行政区, cva: 路网图
                crs?: "WGS84" | string,         // 坐标系
                maximumLevel?: number,   // 允许的最大缩放等级
                minimumLevel?: number,   // 允许的最小缩放等级
            } & Partial<CesiumType.UrlTemplateImageryProvider.ConstructorOptions>,
            // arc gis地图
            arcGIS?:{
                url?: string,
                style?: "img" | "shaded_relief" | "physical" | "terrain", // img: 卫星图，shaded_relief: 电子图, physical: 地形图， terrain: 地形图
            } & CesiumType.ArcGisMapServerImageryProvider.ConstructorOptions,
            // 百度地图

            // 天地图
        }[]
    }[];
    // 相机飞入位置
    cameraFlyToPosition?:{
        lng: number,         // 经度
        lat: number,         // 纬度
        alt: number,         // 高度单位是米
        heading: number,     // 相机的朝向, 单位是角度
        pitch: number,       // 相机的俯仰角, 单位是角度
        roll: number,        // 相机的滚转角, 单位是角度
        duration?: number,   // 动画持续时间, 单位是秒
    },
    // 锁定视角
    lookAtPosition?:{
        center:{            // 视点坐标
            lng: number,
            lat: number,
        },
        heading: number,       // 相机的朝向, 单位是角度
        pitch: number,         // 相机的俯仰角, 单位是角度
        range: number,         // 视点和相机的距离，单位是米
    },
    onMapDidMount?: (gisMapStore: GisMapStore) => void;
}

const Earth3dVis: React.FC<PropsWithChildren<Earth3dVisProps>> = ({children, ...props}) => {
    const { gisMapStore, onMounted } = useEarth3dVis(props);

    return <ProCesium
        cesiumBaseUrl={getEnv().staticPublicPath}
        onMounted={onMounted}
        viewerOptions={{
            // msaaSamples: 4,
            contextOptions:{}
        }}
    >
        {gisMapStore.cesiumUtil && <MapCtx.Provider value={{gisMapStore}}>
            <MapTool />
            {children}
        </MapCtx.Provider>}
    </ProCesium>
}

export default observer(Earth3dVis);

const useEarth3dVis = (props: Earth3dVisProps) => {
    const gisMapStore = useMemo(() => new GisMapStore(), []);

    const onMounted = (params:{CE: CEType,  cesiumUtil: CesiumUtil}) => {
        const {CE, cesiumUtil} = params;
        gisMapStore.setCesiumUtil(cesiumUtil);
        const viewer = cesiumUtil.viewer;

        // 1. 设置viewer相关属性
        viewer.setOptions({
            // msaaSamples: 4, // 1, 2, 4, 8, 默认 1, 越高效果越好, 也越吃性能
            enableFxaa: true,   // 抗锯齿
        });

        // 2. 加载基础图层
        if(props.baseLayers){

            props.baseLayers.forEach(({label, groupLayer}, index) => {
                const layers: any[] = [];
                groupLayer.forEach((item, idx) => {
                    Object.keys(item).forEach((key: keyof Earth3dVisProps["baseLayers"][number]["groupLayer"][number]) => {
                        switch (key){
                            case "amap":{
                                const options = groupLayer[idx][key];
                                layers.push(CE.ImageryLayerFactory.createAmapImageryLayer(options));
                                break
                            }
                            case "arcGIS":{
                                const options = groupLayer[idx][key];
                                if(!options.url && options.style){
                                    if(options.style == "img"){
                                        options.url = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer";
                                    }else if(options.style == "shaded_relief"){
                                        options.url = "https://services.arcgisonline.com/arcgis/rest/services/World_Shaded_Relief/MapServer";
                                    }else if(options.style == "physical"){
                                        options.url = "https://services.arcgisonline.com/arcgis/rest/services/World_Physical_Map/MapServer";
                                    }else if(options.style == "terrain"){
                                        options.url = "https://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer";
                                    }
                                }
                                layers.push(CE.ImageryLayerFactory.createArcGisImageryLayer(options));
                                break;
                            }
                        }
                    })
                })
                viewer.addBaseLayer(layers, {name: label})
            });
        }

        // 3. 回调地图加载完成
        const finished = () => {
            // 回调地图加载完成
            if (typeof props.onMapDidMount === "function") props.onMapDidMount(gisMapStore);

            // // 监听点击事件
            // const onClick = (e: any) => {
            //     console.log("点击事件==>", e)
            // }
            // viewer.on(CE.ViewerEventType.CLICK, onClick);
            // viewer.off(CE.ViewerEventType.CLICK, onClick);

            // // 监听按键控制相机
            // document.addEventListener("keydown", (e) => {
            //     const height = viewer.camera.positionCartographic.height;
            //     const moveRate = height / 100;
            //     if (e.key == 'w') {
            //         // 设置相机向前移动
            //         viewer.camera.moveForward(moveRate)
            //     } else if (e.key == 's') {
            //         // 设置相机向后移动
            //         viewer.camera.moveBackward(moveRate);
            //     } else if (e.key == 'a') {
            //         // 设置相机向左移动
            //         viewer.camera.moveLeft(moveRate);
            //     } else if (e.key == 'd') {
            //         // 设置相机向右移动
            //         viewer.camera.moveRight(moveRate);
            //     } else if (e.key == 'q') {
            //         // 设置相机向左旋转
            //         viewer.camera.lookLeft(CE.Math.toRadians(0.1));
            //     } else if (e.key == 'e') {
            //         // 设置相机向右旋转
            //         viewer.camera.lookRight(CE.Math.toRadians(0.1));
            //     } else if (e.key == 'r') {
            //         // 设置相机向上旋转
            //         viewer.camera.lookUp(CE.Math.toRadians(0.1));
            //     }else if (e.key == 'f') {
            //         // 设置相机向下旋转
            //         viewer.camera.lookDown(CE.Math.toRadians(0.1));
            //     }else if (e.key == 'g') {
            //         // 设置相机逆时针翻滚
            //         viewer.camera.twistLeft(CE.Math.toRadians(0.1));
            //     }else if (e.key == 'h') {
            //         // 设置相机逆时针翻滚
            //         viewer.camera.twistRight(CE.Math.toRadians(0.1));
            //     }
            // });
        }

        // 4. 相机飞入到指定位置
        if(props.cameraFlyToPosition) {
            const { duration, ...position} = props.cameraFlyToPosition;
            viewer.flyToPosition(
                CE.Position.fromObject(position),
                () => {
                    // console.log("获取当前相机的位置->", viewer.cameraPosition)

                    // 回调地图加载完成
                    finished();
                },
                duration
            )
        }else if(props.lookAtPosition){
            // 锁定视角
            viewer.lookAt(props.lookAtPosition);
            // 回调地图加载完成
            finished();
        }else{
            finished();
        }
    }

    // 加载场景组件
    const loadSceneComponents = (viewer: Viewer) => {
        // 罗盘
        viewer.compass.enable = true;

        // 放大缩小
        viewer.zoomController.enable = true;

        // 比例尺
        viewer.distanceLegend.enable = true;

        // 位置信息
        viewer.locationBar.enable = true;

        // 蒙层
        // viewer.loadingMask.enable = true;

        // 鹰眼地图
        // viewer.hawkeyeMap.enable = true;
    }

    return { gisMapStore, onMounted }
}
